// utils/request.js
import { getToken } from '../utils/tokenUtils.js'
// const baseURL = 'http://43.138.144.30:5555'
const baseURL = 'http://1.14.200.13:5555'

class Request {
  constructor(config) {
    this.config = {
      baseURL: config.baseURL || '',
      timeout: config.timeout || 60000,
      header: {
        'Content-Type': 'application/json',
        ...config.header
      }
    };
    this.interceptors = {
      request: config.requestInterceptor || ((config) => config),
      response: config.responseInterceptor || ((response) => response)
    };
    this.pendingRequests = new Map();
  }

  // 生成请求唯一标识
  generateRequestKey(config) {
    const { method, url, data, filePath } = config;
    return [method, url, JSON.stringify(data), filePath].join('&');
  }

  // 添加请求到 pending 队列
  addPendingRequest(config) {
    const requestKey = this.generateRequestKey(config);
    config.cancelToken = new CancelToken((cancel) => {
      if (!this.pendingRequests.has(requestKey)) {
        this.pendingRequests.set(requestKey, cancel);
      }
    });
  }

  // 移除请求
  removePendingRequest(config) {
    const requestKey = this.generateRequestKey(config);
    if (this.pendingRequests.has(requestKey)) {
      const cancel = this.pendingRequests.get(requestKey);
      cancel('Request canceled by the user.');
      this.pendingRequests.delete(requestKey);
    }
  }

  // 发送请求
  request(options) {
    // 合并配置
    const mergedConfig = {
      ...this.config,
      ...options,
      header: {
        ...this.config.header,
        ...options.header
      }
    };

    // 请求拦截
    const interceptedConfig = this.interceptors.request(mergedConfig);

    // 处理重复请求
    this.removePendingRequest(interceptedConfig);
    this.addPendingRequest(interceptedConfig);

    return new Promise((resolve, reject) => {
      const requestTask = uni.request({
        url: interceptedConfig.baseURL + interceptedConfig.url,
        method: interceptedConfig.method || 'GET',
        data: interceptedConfig.data || {},
        header: interceptedConfig.header,
        timeout: interceptedConfig.timeout,
        success: (response) => {
          // 移除已完成请求
          this.removePendingRequest(interceptedConfig);
          
          // 响应拦截
          const interceptedResponse = this.interceptors.response(response);
          
          // 业务状态码处理
          if (interceptedResponse.statusCode === 200) {
            resolve(interceptedResponse.data);
          } else {
            reject(new Error(`HTTP error, status code: ${interceptedResponse.statusCode}`));
          }
        },
        fail: (error) => {
          // 移除失败请求
          this.removePendingRequest(interceptedConfig);
          
          // 错误处理
          if (error.errMsg.includes('timeout')) {
            reject(new Error('Request timed out.'));
          } else if (error.errMsg.includes('abort')) {
            reject(new Error('Request aborted.'));
          } else {
            reject(new Error(`Network error: ${error.errMsg}`));
          }
        },
        complete: () => {
          // 请求完成（无论成功或失败）
        }
      });

      // 存储请求任务以便取消
      interceptedConfig.requestTask = requestTask;
    });
  }

  // 上传文件
  upload(url, filePath, formData = {}, config = {}) {
    // 合并配置
    const mergedConfig = {
      ...this.config,
      ...config,
      url,
      filePath,
      formData,
      header: {
        ...this.config.header,
        ...config.header
      }
    };

    // 请求拦截
    const interceptedConfig = this.interceptors.request(mergedConfig);

    // 处理重复请求
    const requestKey = this.generateRequestKey(interceptedConfig);
    this.removePendingRequest(interceptedConfig);
    this.addPendingRequest(interceptedConfig);

    return new Promise((resolve, reject) => {
      const uploadTask = uni.uploadFile({
        url: interceptedConfig.baseURL + interceptedConfig.url,
        filePath: interceptedConfig.filePath,
        name: interceptedConfig.name || 'img', // 默认文件字段名
        formData: interceptedConfig.formData || {},
        header: interceptedConfig.header,
        timeout: interceptedConfig.timeout,
        success: (response) => {
          // 移除已完成请求
          this.removePendingRequest(interceptedConfig);
          
          // 响应拦截 
          const interceptedResponse = this.interceptors.response({
            ...response,
            data: JSON.parse(response.data || '{}')
          });
          
          // 业务状态码处理
          if (interceptedResponse.statusCode === 200) {
            resolve(interceptedResponse.data);
          } else {
            reject(new Error(`Upload error, status code: ${interceptedResponse.statusCode}`));
          }
        },
        fail: (error) => {
          // 移除失败请求
          this.removePendingRequest(interceptedConfig);
          
          // 错误处理
          if (error.errMsg.includes('timeout')) {
            reject(new Error('Upload timed out.'));
          } else if (error.errMsg.includes('abort')) {
            reject(new Error('Upload aborted.'));
          } else {
            reject(new Error(`Upload error: ${error.errMsg}`));
          }
        },
        complete: () => {
          // 请求完成（无论成功或失败）
        }
      });

      // 存储上传任务以便取消
      interceptedConfig.requestTask = uploadTask;
      
      // 监听上传进度（可选）
      if (interceptedConfig.onProgressUpdate) {
        uploadTask.onProgressUpdate(interceptedConfig.onProgressUpdate);
      }
    });
  }

  // 取消所有请求
  cancelAllRequests() {
    this.pendingRequests.forEach((cancel) => {
      cancel('All requests canceled.');
    });
    this.pendingRequests.clear();
  }

  // 快捷方法
  get(url, data = {}, config = {}) {
    return this.request({ ...config, url, method: 'GET', data });
  }

  post(url, data = {}, config = {}) {
    return this.request({ ...config, url, method: 'POST', data });
  }

  put(url, data = {}, config = {}) {
    return this.request({ ...config, url, method: 'PUT', data });
  }

  delete(url, data = {}, config = {}) {
    return this.request({ ...config, url, method: 'DELETE', data });
  }
}

// 取消令牌类
class CancelToken {
  constructor(executor) {
    this.reason = null;
    this.promise = new Promise((resolve) => {
      executor((message) => {
        if (this.reason) return;
        this.reason = message;
        resolve(this.reason);
      });
    });
  }
}

// 创建请求实例
const request = new Request({
  baseURL: baseURL,
  timeout: 10000 * 20,
  header: {
    'Content-Type': 'application/json'
  },
  // 请求拦截器
  requestInterceptor: (config) => {
    // 添加 token
    const token = getToken();
    if (token) {
      config.header.Authorization = `Bearer ${token}`;
    }
    // 跳过ngrok错误页面
    config.header['ngrok-skip-browser-warning'] = '69420';
    
    // 显示 loading
    uni.showLoading({ title: '加载中...', mask: true });
    return config;
  },
  // 响应拦截器
  responseInterceptor: (response) => {
    // 隐藏 loading
    uni.hideLoading();
    
    // 处理业务错误
    const { data } = response;
    if (data && data.code !== 200) {
      uni.showToast({
        title: data.message || '请求失败',
        icon: 'none'
      });
    }
    
    return response;
  }
});

export default request;